package org.red_cross_service.handler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.red_cross_service.common.response.Response;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 全局异常拦截器
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 添加全局异常处理流程
     *
     * @param e 异常
     * @return 错误信息
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Response exceptionHandler(Exception e) {
        log.error(e.getMessage(), e);
        // http 请求方式错误
        if (e instanceof HttpRequestMethodNotSupportedException) {
            return Response.error("http 请求方式错误");
        }
        // 参数类型错误
        if (e instanceof TypeMismatchException) {
            return Response.error("参数类型错误");
        }
        // json 格式错误
        if (e instanceof HttpMessageNotReadableException) {
            return Response.error("json 格式错误");
        }
        // 参数校验未通过（针对请求体）
        if (e instanceof MethodArgumentNotValidException) {
            List<FieldError> fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
            List<String> msgList = fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.toList());
            return Response.error(String.join(",", msgList));
        }
        // 参数校验未通过（针对 @RequestParam 或 @PathVariable）
        if (e instanceof ConstraintViolationException) {
            Set<ConstraintViolation<?>> violations = ((ConstraintViolationException) e).getConstraintViolations();
            List<String> msgList = violations.stream()
                    .map(violation -> violation.getPropertyPath() + ": " + violation.getMessage())
                    .collect(Collectors.toList());
            return Response.error(String.join(",", msgList));
        }
        return Response.error("系统错误");
    }
}